package com.ninth.element.generated.number;

import com.alibaba.druid.pool.DruidDataSource;
import com.ninth.element.generated.number.generate.fallback.DefaultIdFallback;
import com.ninth.element.generated.number.generate.mysql.MysqlIdTemplate;
import com.ninth.element.generated.number.generate.mysql.MysqlIdWorker;
import com.ninth.element.generated.number.generate.mysql.dao.SerialNumDao;
import com.ninth.element.generated.number.generate.mysql.service.impl.SerialNumServiceImpl;
import com.ninth.element.generated.number.property.MysqlDatasourceWithNumberProperty;
import com.ninth.element.generated.number.property.MysqlWithNumberProperty;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;

import javax.sql.DataSource;

/**
 * @author LiYUJi
 **/
@EnableConfigurationProperties(value = {MysqlDatasourceWithNumberProperty.class, MysqlWithNumberProperty.class})
@ConditionalOnProperty(prefix = NumberStarterConstants.NUMBER_MYSQL_PREFIX, name = "enable", havingValue = "true")
@MapperScan(basePackages = GeneratedNumberMysqlAutoConfiguration.PACKAGE, sqlSessionFactoryRef = "masterSqlSessionFactory")
@Configuration
public class GeneratedNumberMysqlAutoConfiguration {


    @Autowired
    private SerialNumDao serialNumDao;


    /**
     * 精确到 master 目录，以便跟其他数据源隔离
     **/
    static final String PACKAGE = "com.ninth.element.generated.number.generate.mysql.dao";
    static final String MAPPER_LOCATION = "classpath*:mapper/*.xml";

    @Bean(name = "masterDataSource")
    public DataSource masterDataSource(MysqlDatasourceWithNumberProperty mysqlDatasourceWithNumberProperty) {
        DruidDataSource dataSource = new DruidDataSource();
        dataSource.setDriverClassName(mysqlDatasourceWithNumberProperty.getDriverClassName());
        dataSource.setUrl(mysqlDatasourceWithNumberProperty.getUrl());
        dataSource.setUsername(mysqlDatasourceWithNumberProperty.getUsername());
        dataSource.setPassword(mysqlDatasourceWithNumberProperty.getPassword());
        return dataSource;
    }


    @Bean(name = "masterTransactionManager")
    public DataSourceTransactionManager masterTransactionManager(MysqlDatasourceWithNumberProperty mysqlDatasourceWithNumberProperty) {
        return new DataSourceTransactionManager(masterDataSource(mysqlDatasourceWithNumberProperty));
    }

    @Bean(name = "masterSqlSessionFactory")
    public SqlSessionFactory masterSqlSessionFactory(@Qualifier("masterDataSource") DataSource masterDataSource)
            throws Exception {
        final SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();
        sessionFactory.setDataSource(masterDataSource);
        sessionFactory.setMapperLocations(
                new PathMatchingResourcePatternResolver().getResources(GeneratedNumberMysqlAutoConfiguration.MAPPER_LOCATION));
        return sessionFactory.getObject();
    }

    @Bean
    @ConditionalOnMissingBean
    public SerialNumServiceImpl serialNumServiceImpl() {
        return new SerialNumServiceImpl(serialNumDao);
    }

    @Bean
    @ConditionalOnMissingBean
    public MysqlIdWorker mysqlIdWorker() {
        return new MysqlIdWorker();
    }


    @Bean
    @ConditionalOnMissingBean
    public DefaultIdFallback defaultIdFallback() {
        return new DefaultIdFallback();
    }

    @Bean
    @ConditionalOnBean(MysqlIdWorker.class)
    MysqlIdTemplate mysqlIdTemplate() {
        return new MysqlIdTemplate();
    }

}
